home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / dalla rivista / host contacted / jikes.lha / jikes-1.11 / src / stream.h < prev    next >
C/C++ Source or Header  |  2000-01-07  |  12KB  |  409 lines

  1. // $Id: stream.h,v 1.15 2000/01/07 00:25:53 lord Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10. #ifndef stream_INCLUDED
  11. #define stream_INCLUDED
  12.  
  13. #include "config.h"
  14. #include <sys/stat.h>
  15. #include <limits.h>
  16. #include <iostream.h>
  17. #include <stddef.h>
  18. #include <stdio.h>
  19. #include "javadef.h"
  20. #include "javasym.h"
  21. #include "tuple.h"
  22. #include "tab.h"
  23. #include "lookup.h"
  24.  
  25. class Control;
  26. class Input_info;
  27. class Scanner;
  28. class Symbol;
  29. class FileSymbol;
  30. class ZipFile;
  31.  
  32. class StreamError
  33. {
  34. public:
  35.     enum StreamErrorKind
  36.     {
  37.         BAD_TOKEN,
  38.         BAD_OCTAL_CONSTANT,
  39.         EMPTY_CHARACTER_CONSTANT,
  40.         UNTERMINATED_CHARACTER_CONSTANT,
  41.         UNTERMINATED_COMMENT,
  42.         UNTERMINATED_STRING_CONSTANT,
  43.         INVALID_HEX_CONSTANT,
  44.         INVALID_FLOATING_CONSTANT_EXPONENT,
  45.         INVALID_UNICODE_ESCAPE
  46.     };
  47.  
  48.     unsigned start_location,
  49.              end_location;
  50.     StreamErrorKind kind;
  51.  
  52.     void Initialize(StreamErrorKind kind_, unsigned start_location_, unsigned end_location_)
  53.     {
  54.         kind = kind_;
  55.         start_location = start_location_;
  56.         end_location = end_location_;
  57.  
  58.         return;
  59.     }
  60. };
  61.  
  62.  
  63. //
  64. // LexStream holds a stream of tokens generated from an input and
  65. // provides methods to retrieve information from the stream.
  66. //
  67. class LexStream
  68. {
  69. public:
  70.     typedef int TypeIndex;
  71.     typedef int TokenIndex;
  72.     typedef int CommentIndex;
  73.     enum { LEX_INFINITY = INT_MAX }; // the largest possible value for TokenIndex
  74.  
  75.     FileSymbol *file_symbol;
  76.  
  77.     inline TokenIndex Next(TokenIndex i)
  78.          { return (++i < token_stream.Length() ? i : token_stream.Length() - 1); }
  79.  
  80.     inline TokenIndex Previous(TokenIndex i) { return (i <= 0 ? 0 : i - 1); }
  81.  
  82.     inline TokenIndex Peek() { return Next(index); }
  83.  
  84.     inline void Reset(TokenIndex i = 1) { index = Previous(i); }
  85.  
  86.     inline TokenIndex Gettoken() { return index = Next(index); }
  87.  
  88.     inline TokenIndex Gettoken(TokenIndex end_token)
  89.          { return index = (index < end_token ? Next(index) : token_stream.Length() - 1); }
  90.  
  91.     inline TokenIndex Badtoken() { return 0; }
  92.  
  93.     inline unsigned Kind(TokenIndex i) { return tokens[i].Kind(); }
  94.  
  95.     inline unsigned Location(TokenIndex i) { return tokens[i].Location(); }
  96.  
  97.     inline unsigned Line(TokenIndex i) { return FindLine(tokens[i].Location()); }
  98.  
  99.     inline unsigned Column(TokenIndex i) { return columns ? columns[i] : (input_buffer ? FindColumn(tokens[i].Location()) : 0); }
  100.  
  101.     inline bool AfterEol(TokenIndex i) { return (i < 1 ? true : Line(i - 1) < Line(i)); }
  102.  
  103.     inline bool IsDeprecated(TokenIndex i) { return tokens[i].Deprecated(); }
  104.  
  105.     inline TokenIndex MatchingBrace(TokenIndex i) { return tokens[i].additional_info.right_brace; }
  106.  
  107.     wchar_t *NameString(TokenIndex i)
  108.     {
  109.         return (NameSymbol(i) || LiteralSymbol(i) ? tokens[i].additional_info.symbol -> Name()
  110.                                                   : KeywordName(tokens[i].Kind()));
  111.     }
  112.  
  113.     int NameStringLength(TokenIndex i)
  114.     {
  115.         return (NameSymbol(i) || LiteralSymbol(i) ? tokens[i].additional_info.symbol -> NameLength()
  116.                                                   : wcslen(KeywordName(tokens[i].Kind())));
  117.     }
  118.  
  119.     class LiteralSymbol *LiteralSymbol(TokenIndex);
  120.  
  121.     class NameSymbol *NameSymbol(TokenIndex);
  122.  
  123.     char *FileName();
  124.     size_t FileNameLength();
  125.  
  126.     inline int LineLength(unsigned line_no) { return locations[line_no + 1] - locations[line_no]; }
  127.     inline int LineStart(unsigned line_no)  { return locations[line_no]; }
  128.     inline int LineEnd(unsigned line_no)    { return locations[line_no + 1] - 1; }
  129.  
  130.     inline int LineSegmentLength(TokenIndex i)
  131.         { return Tab::Wcslen(input_buffer, tokens[i].Location(), LineEnd(Line(i))); }
  132.  
  133.     //
  134.     // For a sequence of tokens in a given range find out how many large
  135.     // characters they contain and compute the appropriate offset.
  136.     //
  137.     inline int WcharOffset(TokenIndex start, TokenIndex end)
  138.     {
  139.         int offset = 0;
  140.         for (TokenIndex i = start; i <= end; i++)
  141.         {
  142.             for (wchar_t *str = NameString(i); *str; str++)
  143.             {
  144.                  if (*str > 0xff)
  145.                     offset += 5;
  146.             }
  147.         }
  148.  
  149.         return offset;
  150.     }
  151.  
  152.     //
  153.     // When only an end token is supplied, the start token is assume to be the first one on the same line.
  154.     //
  155.     inline int WcharOffset(TokenIndex end)
  156.     {
  157.         TokenIndex start;
  158.         unsigned the_line = Line(end);
  159.         for (start = end; Line(start) == the_line; start--)
  160.             ;
  161.         start++;
  162.  
  163.         return WcharOffset(start, end);
  164.     }
  165.  
  166.     wchar_t *InputBuffer() { return input_buffer; }
  167.     size_t InputBufferLength() { return input_buffer_length; }
  168.  
  169.     CommentIndex FirstComment(TokenIndex);
  170.  
  171.     inline int NumTypes() { return type_index.Length(); }
  172.     inline TokenIndex Type(int i) { return types[i]; }
  173.  
  174.     inline int NumTokens() { return token_stream.Length(); }
  175.  
  176.     inline int NumComments() { return comment_stream.Length(); }
  177.  
  178.     inline TokenIndex PrecedingToken(CommentIndex i) { return comments[i].previous_token; }
  179.  
  180.     inline unsigned CommentLocation(CommentIndex i)  { return comments[i].location; }
  181.  
  182.     inline wchar_t *CommentString(CommentIndex i)    { return comments[i].string; }
  183.  
  184.     inline int CommentStringLength(CommentIndex i)   { return comments[i].length; }
  185.  
  186.     inline int NumBadTokens() { return bad_tokens.Length(); }
  187.  
  188. #ifdef TEST
  189.     int file_read;
  190. #endif
  191.  
  192.     //*
  193.     //* Constructors and Destructor.
  194.     //*
  195.     LexStream(Control &control_, FileSymbol *file_symbol_) : file_symbol(file_symbol_),
  196. #ifdef TEST
  197.                                                              file_read(0),
  198. #endif
  199.                                                              tokens(NULL),
  200.                                                              columns(NULL),
  201.                                                              token_stream(12, 16),
  202.                                                              comments(NULL),
  203.                                                              comment_stream(10, 8),
  204.                                                              locations(NULL),
  205.                                                              line_location(12, 8),
  206.                                                              initial_reading_of_input(true),
  207.                                                              input_buffer(NULL),
  208.                                                              input_buffer_length(0),
  209.                                                              comment_buffer(NULL),
  210.                                                              control(control_)
  211.     {}
  212.  
  213.     bool ComputeColumns()
  214.     {
  215.         RereadInput();
  216.         if (input_buffer)
  217.             InitializeColumns();
  218.  
  219.         DestroyInput();
  220.  
  221.         return (columns != NULL);
  222.     }
  223.  
  224.     void RereadInput();
  225.     ~LexStream();
  226.  
  227.  
  228.     void DestroyInput()
  229.     {
  230.         delete [] input_buffer;
  231.         input_buffer = NULL;
  232.  
  233.         delete [] comment_buffer;
  234.         comment_buffer = NULL;
  235.     }
  236.  
  237.     void SortMessages();
  238.     void PrintMessages();
  239.     void PrintEmacsMessage(int);
  240.     void PrintSmallSource(int);
  241.     void PrintLargeSource(int);
  242.     void PrintMessage(StreamError::StreamErrorKind);
  243.  
  244.     void SetUpComments()
  245.     {
  246.         RereadInput();
  247.         //
  248.         // Calculate the length of the string required to save the comments.
  249.         // Allocate the buffer, save the comments in the buffer and update their
  250.         // respective "string" pointer.
  251.         //
  252.         int length = 0,
  253.             i;
  254.  
  255.         for (i = 1; i < comment_stream.Length(); i++)
  256.             length += (comments[i].length + 1);
  257.         comment_buffer = new wchar_t[length];
  258.         wchar_t *ptr = comment_buffer;
  259.         for (i = 1; i < comment_stream.Length(); i++)
  260.         {
  261.             memmove(ptr, &(input_buffer[comments[i].location]), comments[i].length * sizeof(wchar_t));
  262.             comments[i].string = ptr;
  263.             ptr += comments[i].length;
  264.             *ptr++ = U_NULL;
  265.         }
  266.  
  267.         return;
  268.     }
  269.  
  270. #ifdef TEST
  271. void LexStream::Dump(); // temporary function used to dump token stream.
  272. #endif
  273.  
  274.     //
  275.     // Return the total size of space allocated for the tokens.
  276.     //
  277.     size_t TokenSpaceAllocated(void)
  278.     {
  279.         return token_stream.Length() * sizeof(Token);
  280.     }
  281.  
  282.     //
  283.     // Return the total size of space allocated for the comments.
  284.     //
  285.     size_t CommentSpaceAllocated(void)
  286.     {
  287.         return comment_stream.Length() * sizeof(Comment);
  288.     }
  289.  
  290. private:
  291.  
  292.     int hexvalue(wchar_t ch);
  293.     
  294.     enum UnicodeLexerState
  295.     {
  296.         RAW,
  297.         CR,
  298.         QUOTE,
  299.         UNICODE_ESCAPE,
  300.         UNICODE_ESCAPE_DIGIT_0,
  301.         UNICODE_ESCAPE_DIGIT_1,
  302.         UNICODE_ESCAPE_DIGIT_2
  303.     };
  304.     
  305.     friend class Scanner;
  306.  
  307.     class Token
  308.     {
  309.         //
  310.         // It is expected that a location will be set for every token. Therefore,
  311.         // as we are setting the location, we also reset the deprecated bit to 0.
  312.         // If it is subsequently discovered that the token is followed by one or more
  313.         // deprecated tags then the bit is set to 1 by an invocation of the
  314.         // function SetDeprecated. Note that a better way to resetting all the bits in
  315.         // "info" is to use the function ResetInfoAndSetLocation defined below, instead
  316.         // of using SetLocation
  317.         //
  318.         inline void SetLocation(unsigned location) { assert(location <= 0x00FFFFFF); info = (info & 0x0000007F) | (location << 8); }
  319.  
  320.     public:
  321.         unsigned info;
  322.         union
  323.         {
  324.             Symbol   *symbol;
  325.             TokenIndex right_brace;
  326.         } additional_info;
  327.  
  328.         //
  329.         // To just reset the info, this function should be invoked with a location value of 0.
  330.         //
  331.         inline void ResetInfoAndSetLocation(unsigned location)
  332.         {
  333.             assert(location <= 0x00FFFFFF);
  334.             info = (location << 8);
  335.             additional_info.symbol = NULL;
  336.         }
  337.  
  338.         inline unsigned Location()                   { return (info >> 8); }
  339.         inline void SetKind(unsigned kind)           { assert(kind <= 0x0000007F); info = (info & 0xFFFFFF80) | kind; }
  340.         inline unsigned Kind()                       { return (info & 0x0000007F); }
  341.         inline void SetDeprecated()                  { info |= 0x00000080; }
  342.         inline bool Deprecated()                     { return ((info & 0x00000080) != 0); }
  343.  
  344.         inline void SetSymbol(Symbol *symbol)        { additional_info.symbol = symbol; }
  345.         inline void SetRightBrace(TokenIndex rbrace) { additional_info.right_brace = rbrace; }
  346.     };
  347.  
  348.     TokenIndex GetNextToken(unsigned location = 0)
  349.     {
  350.         TokenIndex index = token_stream.NextIndex();
  351.         token_stream[index].ResetInfoAndSetLocation(location);
  352.  
  353.         return index;
  354.     }
  355.  
  356.     class Comment
  357.     {
  358.     public:
  359.         TokenIndex previous_token;
  360.         unsigned   location;
  361.         unsigned   length;
  362.         wchar_t   *string;
  363.     };
  364.  
  365.     Tuple<StreamError> bad_tokens;
  366.  
  367.     TokenIndex index;
  368.     Token *tokens;
  369.     unsigned short *columns;
  370.     ConvertibleArray<Token> token_stream;
  371.     Comment *comments;
  372.     ConvertibleArray<Comment> comment_stream;
  373.     unsigned *locations;
  374.     ConvertibleArray<unsigned> line_location;
  375.     TokenIndex *types;
  376.     ConvertibleArray<TokenIndex> type_index;
  377.  
  378.     void InitializeColumns();
  379.     void CompressSpace();
  380.  
  381.     bool initial_reading_of_input;
  382.  
  383.     wchar_t *input_buffer;
  384.     size_t input_buffer_length;
  385.     wchar_t *comment_buffer;
  386.  
  387.     Control &control;
  388.  
  389.     void ReadInput();
  390.     void ProcessInput(char *, long);
  391.     void ProcessInputAscii(char *, long);
  392. #ifdef HAVE_LIB_ICU_UC
  393.     void ProcessInputUnicode(char *, long);
  394. #endif  
  395.  
  396.     wchar_t *KeywordName(int);
  397.  
  398.     unsigned FindLine(unsigned location);
  399.  
  400.     unsigned FindColumn(unsigned location)
  401.     {
  402.         assert(locations);
  403.  
  404.         return Tab::Wcslen(input_buffer, locations[FindLine(location)], location);
  405.     }
  406. };
  407.  
  408. #endif
  409.